package com.zthz.douxing.data

import com.zthz.douxing.utils.CommonUtil
import groovyx.net.http.HTTPBuilder
import org.apache.commons.lang.StringUtils
import org.apache.http.client.ClientProtocolException
import org.codehaus.groovy.runtime.typehandling.GroovyCastException

import javax.annotation.PostConstruct

import static grails.async.Promises.*
import static groovyx.net.http.ContentType.JSON
import static groovyx.net.http.Method.GET

/**
 * 用于获取天气的Job. 调用接口参考 <a>http://www.k780.com/api/Weather_Today</a>
 * Created by JetGeng on 4/5/14.
 */
class K780WeathFetchJob {

    def cityInfoService
    def redisKeyGenernateService
    def grailsApplication
    def handlerRefs = []
    def config
    def url = 'http://api.k780.com:88/'
    def timeBatchCount = 100 //默认并发请求的最大的数

    /**
     http://api.k780.com:88/?app=weather.today&weaid=1&appkey=10003&sign=b59bc3ef6191eb9f747dd4e83c99f2a4&format=json
     http://api.k780.com:88/?app=weather.future&cityid=101010100&appkey=10003&sign=b59bc3ef6191eb9f747dd4e83c99f2a4&format=json
     **/


    static triggers = {
        //每2个小时执行一次
        cron name: 'k780WeathFetchJob', cronExpression: CommonUtil.CRON_EXPRESSION
    }


    def group = "fetchData"


    public K780WeathFetchJob() {
        //进行初始化，获取相关信息

    }

    @PostConstruct
    public void init() {
        timeBatchCount = getConfig().timeBatchCount
    }

    private getHandlerRefs() {
        if (getConfig().handler.size() != handlerRefs.size()) {
            handlerRefs.clear()
            handlerRefs = createRefList(getConfig().handler)
        }
        return handlerRefs
    }

    private createRefList = { names -> names.collect { name -> grailsApplication.mainContext.getBean(name) } }

    def getConfig() {
        if (config == null) {
            config = grailsApplication.config.data."${this.getClass().getSimpleName()}"
        }
        return config
    }
    /**
     * 采用并行的方式批量获取当前天气
     * @return
     */
    def execute() {
        def currentData = new Date()
        def cityCodes = cityInfoService.getAllCityInfo()
        if (cityCodes == null) {
            return
        }
        log.debug("the number of cityCodes is : ${cityCodes.size()}")
        def willExeCityCodes = cityCodes.collate(cityCodes.size().intdiv(timeBatchCount))

        willExeCityCodes.each { it ->
            //分批次执行
            def fetchTasks = getFetchTask(it)
            log.debug("the number of task is : ${fetchTasks.size()}")
            waitAll(fetchTasks)
            onError(fetchTasks) { Throwable t ->
                println "An error occured ${t.message}"
            }
        }
    }

    /**
     * 根据给定的城市信息，生成一个task列表
     * @param cityInfoList
     * @return
     */
    def getFetchTask(cityInfoList) {
        def handles = getHandlerRefs()
        if (!(cityInfoList != null && cityInfoList.size() > 0)) {
            return null
        }
        def fetchTasks = []
        cityInfoList.each {
            def currentData = new Date()
            def cityInfo = it
            if (StringUtils.isEmpty(cityInfo.code)) {
                return
            }
            fetchTasks << task {
                def http = new HTTPBuilder(url)
                try {
                        http.request(GET, JSON) {
                        uri.path = "/"
                        uri.query = [app: 'weather.today', appkey: getConfig()?.appkey,
                                sign: getConfig()?.Sign, weaid: cityInfo.code, format: "json"]

                        response.success = {
                            resp, json ->
                                def key = redisKeyGenernateService.getRedisKey(DataType.Weather.name(),
                                        currentData.format("yyyy-MM-dd") + "_" + cityInfo.code)
                                def context = [:]
                                context.cityCode = cityInfo.code
                                context.targetKey = key
                                context.nowDate = currentData.format("yyyy-MM-dd")
                                log.debug("read to get weath from k780 for ${key}")
                                handles.each {
                                    handle ->
                                        if (handle.metaClass.respondsTo(handle, 'convert', [Object.getClass(), [:].getClass()])) {
                                            def currentTarget = context.target
                                            if (currentTarget == null) {
                                                currentTarget = json
                                            }
                                            handle.convert(currentTarget, context)
                                        }
                                }
                                //成功的话，发出获取成功的消息
                                return json
                        }
                    }
                } catch (GroovyCastException e) {
                    log.error("+++++++++++++++++" + e.getMessage(), e)
                } catch (ClientProtocolException e) {
                    log.error("=================" + e.getMessage(), e)
                } catch (IOException ioException) {
                    //可以发送获取数据失败的event
                    log.error("_________________" + ioException.getMessage(), ioException)
                }
            }
        }
        fetchTasks
    }
}
